package com.panfeng.xcloud.common.core.utils;

import com.panfeng.xcloud.common.core.page.PageResponse;
import com.panfeng.xcloud.common.core.web.vo.PageResponseVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;

import java.io.Serializable;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
public abstract class ConvertUtils {

    /**
     * 分页DTO转VO
     * @param pageResponse 分页DTO
     * @param voClass VO类型
     * @param <D> DTO
     * @param <V> VO
     * @return PageResponseVO<V>
     */
    public static <D extends Serializable, V extends Serializable> PageResponseVO<V> convertPage(PageResponse<D> pageResponse, Class<V> voClass) {
        PageResponseVO<V> pageResponseVO = new PageResponseVO<>();
        BeanUtils.copyProperties(pageResponse, pageResponseVO);

        pageResponseVO.setItems(convert(pageResponse.getItems(), voClass));

        return pageResponseVO;
    }

    /**
     * 转换对象列表
     * @param source 源对象数组
     * @param targetClass 目标类型
     * @param <S> 源类型
     * @param <T> 目标类型
     * @return 目标对象列表
     */
    public static <S, T> List<T> convert(List<S> source, Class<T> targetClass) {
        if(source == null) {
            return null;
        }
        if(source.isEmpty()) {
            return Collections.EMPTY_LIST;
        }
        return source.stream().map(s -> convert(s, targetClass)).collect(Collectors.toList());
    }

    /**
     * 转换单个对象
     * @param source 源对象
     * @param targetClass 目标类型
     * @param <S> 源类型
     * @param <T> 目标类型
     * @return 目标对象
     */
    public static <S, T> T convert(S source, Class<T> targetClass) {
        if(source == null) {
            return null;
        }
        T target = newInstance(targetClass);

        return copyProperties(source, target);
    }

    /**
     * 复制属性， 采用Spring BeanUtils
     * 只复制： 类型&属性名都一致的， 其他的通通忽略
     * @param source 源对象
     * @param target 目标对象
     * @param <S> 源类型
     * @param <T> 目标类型
     * @return 目标对象
     */
    public static <S, T> T copyProperties(S source, T target) {
        BeanUtils.copyProperties(source, target);
        return target;
    }

    /**
     * 如果t为空， 则返回空对象。 否则返回t
     * @param t 对象
     * @param type 对象类型
     * @param <T> 对象类型
     * @return t或type.newInstance
     */
    public static <T> T null2Empty(T t, Class<T> type) {
        return t == null ? newInstance(type) : t;
    }

    /**
     * 根据Class信息创建实例
     * @param type Class类型信息
     * @param <T> 类型
     * @return 实例
     * @throws RuntimeException 构造器调用失败
     */
    public static <T> T newInstance(Class<T> type) {
        try {
            return type.newInstance();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

}
